#pragma once 
#include<assert.h>
#include<cstring>
#include<iostream>
#include<assert.h>
using std::ostream;
using std::istream;
namespace MyS
{
  class string
  {
    public:
    const static size_t npos = -1;
      typedef char* iterator;
      typedef const char* const_iterator;
      iterator begin()
      {
        return _str;
      }
      iterator begin()const 
      {
        return _str;
      }
      iterator end()
      {
        return _str + _size;
      }
      iterator end()const{
        return _str + _size;
      }
      char* c_str()
      {
        return _str;
      }
      
      string(const char* str = "")
      {
        _size = strlen(str);
        _capacity = _size;
        _str = new char[_capacity+1];
        strcpy(_str,str);
      }
     string(const string& s)
     {
        _size = s._size;
        _capacity = s._capacity;
        _str = new char[s._capacity+1];
        strcpy(_str,s._str);
     }

      ~string()
      {
        delete[] _str;
        _str = nullptr;
        _size = 0;
        _capacity = 0;
      }
      string& operator=(const string& s)
      {
        _size = s._size;
        _capacity = s._capacity;
        if(_str != nullptr)
        {
          delete[] _str;
        }
        _str = new char[s._capacity+1];
        strcpy(_str,s._str);
        return *this;
      }
      char& operator[](int i)
      {
        return _str[i];
      }
      char& operator[](int i)const
      {
        return _str[i];
      }
      char& at(int i)
      {
        return _str[i];
      }
      size_t find(const string &s,size_t pos = 0) const
      {
        assert(pos < _size && pos >= 0);
        char* f = strstr(_str+pos,s._str);
        return f-begin();
      }
      size_t find(const char* s,size_t pos = 0) const
      {
        assert(pos < _size && pos >= 0);
        char* f = strstr(_str+pos,s);
        return f-begin();
      }
      size_t find(const char ch,size_t pos = 0) const
      {
        assert(pos < _size && pos >= 0);
        size_t i = pos;
        while(i)
        {
          if(_str[i++]==ch)
          {
            return --i;
          }
        }
          return npos;
      }
      void reserve(size_t capacity)
      {
        if(_capacity < capacity)
        {
  
            _capacity = capacity;
            char* tmp = new char[_capacity+1];
            strcpy(tmp,_str);
            delete[] _str;
            _str = tmp;
        }
      }
      void resize(size_t capacity,const char a = '\0')
      {
          if(_size > capacity)
          {
            _size = capacity;
            _str[_size] = '\0';
          }
          else{
            if(_capacity < capacity)
            {
              this->reserve(capacity);
            }
            while(_size < capacity)
            {
              _str[_size++] = a;
            }
            _str[_size] = '\0';
          }
      }
      void push_back(const char s)
      {
        if(_size == _capacity)
        {
          _capacity == 0 ? _capacity = 4 :_capacity*=2;
          char* tmp = new char[_capacity+1];
          strcpy(tmp,_str);
          delete[] _str;
          _str = tmp;
        }
        _str[_size] = s;
        ++_size;
        _str[_size] = '\0';
      }
      void append(const char* s)
      {
        int pos = strlen(s);
        if(_capacity < _size+pos)
        {
          _capacity = _size+pos;
          char* tmp = new char[_capacity+1];
          strcpy(tmp,_str);
          strcat(tmp,s);
          delete[] _str;
          _str = tmp;
        }
        _size += pos;
      }
      string& operator+=(string& s)
      {
        append(s.c_str());
        return *this;
      }
      string& operator+=(const char* s)
      {
        append(s);
        return *this;
      }
      string& operator+=(const char s)
      {
        this->push_back(s);
        return *this;
      }
      bool operator==(const string &s)
      {
        if(strcmp(_str,s._str) == 0)
        {
          return true;
        }
        return false;
      }
      bool operator>(const string &s)
      {
        if(strcmp(_str,s._str) > 0)
        {
          return true;
        }
        return false;

      }
      bool operator<(const string &s)
      {
        if(!(*this > s || *this == s))
        {
          return true;
        }
        return false;
      }
      bool operator<=(const string &s)
      {
        if(*this < s && *this == s)
        {
          return true;
        }
        return false;
      }
      bool operator>=(const string &s)
      {
        if(*this > s && *this == s)
        {
          return true;
        }
        return false;
      }
      bool operator!=(const string &s)
      {
        if(!(*this == s))
        {
          return true;
        }
        return false;
      }
      void insert(size_t pos,const char s)
      {
        size_t len = _size + 1;
        if(_capacity < len)
        {
          reserve(len);
        }
        _size += 1;
        for(size_t i = _size;i > pos;i--)
        {
          _str[i] = _str[i-1];
        }
        _str[pos] = s;
      }
      void insert(size_t pos,const char* s)
      {
        size_t end = _size+strlen(s);
        size_t len = strlen(s);
        if(_capacity < end)
        {
          reserve(end);
        }
        for(size_t i = end;i > pos;i--)
        {
          _str[i] = _str[i-len];
        }
        while(*s)
        {
          _str[pos++] = *(s++);
        }
        _size = end;
      }
      void push_pop()
      {
        --_size;
        _str[_size] = '\0';
      }
      void erase(size_t pos,const size_t count = npos)
      {
        if(_size >= pos+count)
        {
          size_t end = _size - count;
          for(size_t i = pos;i < end;i++)
          {
            _str[i] = _str[i+count];
          }
          _size -= count;
        }
        else{
          _size = pos;
        }
        _str[_size] = '\0';
      }
      size_t size()
      {
        return _size;
      }
      size_t capacity()
      {
        return _capacity;
      }
      void clear()
      {
        *this = string();
      }


    private:
      char* _str;
      size_t _size;
      size_t _capacity;
    public:
  };
  ostream& operator<<(ostream& cout,const string& s)
  {
    for(auto ch: s)
    {
      cout << ch;
    }
    return cout;
  }
  istream& operator>>(istream& cin,string& s)
  {
    s.clear();
    char ch;
   char buff[128] = {"\0"};
   int i = 0;
   ch = cin.get();
   while(ch != ' ' &&  ch != '\n')
   {
     buff[i++] = ch;
     if(i == 127)
     {
       s += buff;
       i = 0;
      memset(buff,'\0',128);
     }
     ch = cin.get();
   }
   s += buff;
    return cin;
  }
}
